<template>
  <AdVxeModal
    v-bind="$attrs"
    :destroyOnClose="true"
    @register="registerModal"
    :id="'organization-transfer-modal'"
    :showCancel="false"
    :showOk="false"
    :close-func="handleClose"
    @ok="handleOk"
  >
    <template #insertFooter>
      <a-button type="default" @click="handleCancel" :loading="loadingRef">
        {{ cancelText }}
      </a-button>
      <Authority :value="okAuthorityCode" v-if="okAuthority === true">
        <a-button type="primary" @click="handleOk" :loading="loadingRef">
          {{ okText }}
        </a-button>
      </Authority>
      <a-button type="primary" @click="handleOk" v-if="okAuthority !== true" :loading="loadingRef">
        {{ okText }}
      </a-button>
    </template>

    <Transfer
      v-model:targetKeys="targetKeys"
      :dataSource="dataSource"
      :showSearch="search"
      :filterOption="filterOption"
      :render="(item: any) => item.description"
      :showSelectAll="false"
      @change="onChange"
      style="height: 100%"
    >
      <template #children="{ direction, selectedKeys, onItemSelect }">
        <Tree
          v-if="direction === 'left'"
          block-node
          checkable
          check-strictly
          default-expand-all
          :checked-keys="[...selectedKeys, ...targetKeys]"
          :tree-data="treeData"
          @check="
            (_: any, props: any) => {
              onChecked(props, [...selectedKeys, ...targetKeys], onItemSelect);
            }
          "
          @select="
            (_: any, props: any) => {
              onChecked(props, [...selectedKeys, ...targetKeys], onItemSelect);
            }
          "
        />
      </template>
    </Transfer>
  </AdVxeModal>
</template>

<script lang="ts">
  import type { PropType } from 'vue';
  import { defineComponent, ref } from 'vue';
  import { useI18n } from '@/hooks/web/useI18n';
  import { Transfer, Tree } from 'ant-design-vue';
  import { AdVxeModal, useModalInner } from '@/components/AdVxeModal';
  import { Authority } from '@/components/Authority';

  import { OrganizationTypeEnum } from '@/enums/organizationTypeEnum';
  import { OrganizationTreeNode } from '@/api/identity/model';
  import { getOrganizationTree } from '@/api/identity';
  import { getOrganizationNodes } from '@/api/identity/admin/organization/index';
  import { OrganizationNodeSimple } from '@/api/identity/admin/organization/model';

  import { isFunction } from '@/utils/is';
  import { propTypes } from '@/utils/propTypes';

  const { t } = useI18n();

  interface OrganizationTrees extends OrganizationTreeNode {
    key: string;
    title: string;
    description: string;
    disabled: boolean;

    /** 子项集合 */
    children: OrganizationTrees[];
  }

  export default defineComponent({
    name: 'OrganizationTransferModal',
    components: { AdVxeModal, Transfer, Tree, Authority },
    props: {
      /** 显示搜索框 */
      search: propTypes.bool.def(true),
      /** 取消按钮文本 */
      cancelText: propTypes.string.def(t('common.cancelText')),
      /** 关闭回调，返回true关闭窗体 */
      closeFunc: {
        type: Function as PropType<
          (targetKeys: string[], orgNodes: OrganizationTrees[], record: any) => Promise<boolean>
        >,
        default: null,
      },
      /** 确认按钮文本 */
      okText: propTypes.string.def(t('common.okText')),
      /** 确认按钮权限（默认不开启） */
      okAuthority: propTypes.bool.def(false),
      /** 确认按钮权限代码（按钮权限开启有效） */
      okAuthorityCode: {
        type: [Number, Array, String] as PropType<string | string[]>,
        default: '',
      },
      /** 确定回调，返回true关闭窗体 */
      okFunc: {
        type: Function as PropType<
          (targetKeys: string[], orgNodes: OrganizationTrees[], record: any) => Promise<boolean>
        >,
        default: null,
      },
    },
    setup(props: { closeFunc?: any; okFunc?: any }) {
      // const { t } = useI18n();
      const recordRef = ref<any>();
      const targetKeys = ref<string[]>([]);
      const dataSource = ref<OrganizationTrees[]>([]);
      const treeData = ref<OrganizationTrees[]>([]);

      //#region "加载状态"
      const loadingRef = ref(false);
      /** 开启加载状态 */
      function openLoading() {
        changeLoading(true);
        setModalProps({ okLoading: true, cancelLoading: true });
        loadingRef.value = true;
      }
      /** 关闭加载状态 */
      function closeLoading() {
        changeLoading(false);
        setModalProps({ okLoading: false, cancelLoading: false });
        loadingRef.value = false;
      }
      //#endregion

      const onChange = (nextTargetKeys: string[]) => {
        targetKeys.value = nextTargetKeys;
      };

      /** 获取组织树节点 */
      async function getOrganizationNode(): Promise<OrganizationTrees[]> {
        const ajaxResult = await getOrganizationTree();
        if (ajaxResult.Succeeded) {
          let orgTreeNodes = ajaxResult.Data as OrganizationTrees[];
          if (orgTreeNodes?.length > 0) {
            orgTreeNodes.forEach((treeNode) => {
              setOrganizationNodeDisabled(treeNode);
            });
          }
          // console.log('orgTreeNodes', orgTreeNodes);
          return orgTreeNodes;
        }
        return [];
      }
      /** 处理组织树节点可选属性 */
      function setOrganizationNodeDisabled(treeNode: OrganizationTrees, descr?: string) {
        treeNode.key = treeNode.Id.toString();
        treeNode.title = treeNode.Name;
        treeNode.description = descr ? `${descr} -> ${treeNode.Name}` : treeNode.Name;
        treeNode.disabled = treeNode.IsLocked;
        treeNode.children = treeNode.Items as OrganizationTrees[];
        if (treeNode.EnableLogin === false && treeNode.Type !== OrganizationTypeEnum.Department) {
          treeNode.disabled = true;
        }
        treeNode.children.forEach((subItem) => {
          setOrganizationNodeDisabled(subItem, treeNode.description);
        });
      }
      /** 压平组织树节点 */
      function flatten(list: OrganizationTrees[] = []) {
        list.forEach((item) => {
          dataSource.value.push(item);
          flatten(item.children);
        });
      }

      const [registerModal, { setModalProps, closeModal, changeLoading }] = useModalInner(
        async (data) => {
          changeLoading(true);
          try {
            // console.log('data', data);
            dataSource.value = [];
            targetKeys.value = [];
            let orgNodes: OrganizationNodeSimple[] = [];

            // 获取组织机构树节点
            const orgTrees = await getOrganizationNode();
            // 设置穿梭框数据源
            treeData.value = orgTrees;
            flatten(orgTrees);
            if (data.organizationNodes && data.organizationNodes.length > 0) {
              orgNodes = data.organizationNodes as OrganizationNodeSimple[];
            } else {
              const checkedKeys: string[] = data.checkedKeys ? (data.checkedKeys as string[]) : [];
              orgNodes = (await getOrganizationNodes(checkedKeys)) as OrganizationNodeSimple[];
            }
            if (orgNodes && orgNodes.length > 0) {
              targetKeys.value = orgNodes
                .filter((item) => item.IsChecked === true)
                .map((item) => item.Id.toString());
            }
            if (data.record) {
              recordRef.value = data.record;
            }
          } finally {
            changeLoading(false);
          }
        },
      );

      /** 处理关闭事件 */
      async function handleClose() {
        openLoading();

        const { closeFunc } = props;
        try {
          if (closeFunc && isFunction(closeFunc)) {
            const result = await closeFunc(
              [...targetKeys.value],
              [...dataSource.value],
              recordRef.value,
            );
            // console.log('closeFunc', result);
            return result;
          }
        } finally {
          closeLoading();
        }
        // console.log('handleClose', true);
        return true;
      }
      /** 处理关闭按钮 */
      async function handleCancel() {
        let innerClose = true;
        openLoading();
        const { closeFunc } = props;
        try {
          if (closeFunc && isFunction(closeFunc)) {
            //重新设置数据源选中值
            innerClose = await closeFunc(
              [...targetKeys.value],
              [...dataSource.value],
              recordRef.value,
            );
            // console.log('closeFunc', innerClose);
          }
        } finally {
          closeLoading();
        }
        // console.log('handleCancel', innerClose);
        if (innerClose) {
          closeModal();
        }
      }
      /** 处理确定按钮 */
      async function handleOk() {
        openLoading();
        const { okFunc } = props;
        try {
          if (okFunc && isFunction(okFunc)) {
            const canClose = await okFunc(
              [...targetKeys.value],
              [...dataSource.value],
              recordRef.value,
            );
            if (canClose) {
              closeModal();
            }
          } else {
            closeModal();
          }
        } finally {
          closeLoading();
        }
      }

      function isChecked(selectedKeys: (string | number)[], eventKey: string | number) {
        return selectedKeys.indexOf(eventKey) !== -1;
      }
      const onChecked = (
        e: any,
        checkedKeys: string[],
        onItemSelect: (n: any, c: boolean) => void,
      ) => {
        const { eventKey } = e.node;
        onItemSelect(eventKey, !isChecked(checkedKeys, eventKey));
      };
      /** 筛选配置 */
      const filterOption = (inputValue: string, option: any) => {
        // OrganizationTrees
        return (
          option.key.toLowerCase().indexOf(inputValue.toLowerCase()) > -1 ||
          option.title.toLowerCase().indexOf(inputValue.toLowerCase()) > -1 ||
          option.description.toLowerCase().indexOf(inputValue.toLowerCase()) > -1
        );
      };

      return {
        t,
        loadingRef,
        registerModal,
        handleClose,
        handleCancel,
        handleOk,
        dataSource,
        treeData,
        targetKeys,
        onChange,
        onChecked,
        filterOption,
        handleResizeColumn: (w: any, col: any) => {
          col.width = w;
        },
      };
    },
  });
</script>
